-module(rtps_dw).

%%% @doc This is what a data writer should look like more or less.

-behaviour(gen_server).

%% -include_lib("kernel/include/logger.hrl").
-include("rtps.hrl").
-include("rtps_history_cache.hrl").

%% API
-export([start_link/2, write/3, unregister/3, dispose/3]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
	 terminate/2, code_change/3]).

-record(data, {w :: pid(), whc :: pid()}).

%%%===================================================================
%%% API
%%%===================================================================

start_link(W, WHC) ->
    gen_server:start_link(?MODULE, [W, WHC], []).

-spec write(Pid, Data_value, Instance_handle) -> ok | {error, Reason} when
      Pid :: pid(),
      Data_value :: term(),
      Instance_handle :: term(),
      Reason :: term().
write(Pid, Data_value, Instance_handle) ->
    gen_server:call(Pid, {write, Data_value, Instance_handle}).

-spec unregister(Pid, Data_value, Instance_handle) -> ok | {error, Reason} when
      Pid :: pid(),
      Data_value :: term(),
      Instance_handle :: term(),
      Reason :: term().
unregister(Pid, Data_value, Instance_handle) ->
    gen_server:call(Pid, {unregister, Data_value, Instance_handle}).

-spec dispose(Pid, Data_value, Instance_handle) -> ok | {error, Reason} when
      Pid :: pid(),
      Data_value :: term(),
      Instance_handle :: term(),
      Reason :: term().
dispose(Pid, Data_value, Instance_handle) ->
    gen_server:call(Pid, {dispose, Data_value, Instance_handle}).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

%% @private
init([W, WHC]) ->
    {ok, #data{w = W, whc = WHC}}.

%% @private
handle_call({write, Data_value, Instance_handle}, _From, #data{w = W, whc = WHC} = Data) ->
    Reply = case rtps_writer:new_change(W, alive, Data_value, Instance_handle) of
		{ok, Change} ->
		    rtps_history_cache:add_change(WHC, Change);
		Error ->
		    Error
	    end,
    {reply, Reply, Data};
handle_call({Action, _Data_value, Instance_handle}, _From, #data{w = W, whc = WHC} = Data) ->
    Reply = case rtps_writer:topic_kind(W) of
		with_key ->
		    Kind = case Action of
			       unregister -> not_alive_unregistered;
			       dispose -> not_alive_disposed
			   end,
		    case rtps_writer:new_change(W, Kind, undefined, Instance_handle) of
			{ok, Change} ->
			    rtps_history_cache:add_change(WHC, Change);
			Error ->
			    Error
		    end;
		no_key ->
		    ok
	    end,
    {reply, Reply, Data};
handle_call(_Request, _From, Data) ->
    Reply = ok,
    {reply, Reply, Data}.

%% @private
handle_cast(_Msg, Data) ->
    {noreply, Data}.

%% @private
handle_info(_Info, Data) ->
    {noreply, Data}.

%% @private
terminate(_Reason, _Data) ->
    ok.

%% @private
code_change(_OldVsn, Data, _Extra) ->
    {ok, Data}.

%%%===================================================================
%%% Internal functions
%%%===================================================================
    
